<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Three.js Snowfall Effect with Canvas Snowflake</title>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
<script>
    let scene, camera, renderer;
    let snowflakes = [];

    init();
    animate();

    function init() {
        scene = new THREE.Scene();
        camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        renderer = new THREE.WebGLRenderer();

        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        camera.position.z = 50;

        // 创建雪花材质
        let snowflakeCanvas = document.createElement('canvas');
        snowflakeCanvas.width = 16;
        snowflakeCanvas.height = 16;
        let ctx = snowflakeCanvas.getContext('2d');
        ctx.fillStyle = '#ffffff';
        ctx.beginPath();
        ctx.arc(8, 8, 4, 0, Math.PI * 2);
        ctx.fill();

        let snowflakeTexture = new THREE.CanvasTexture(snowflakeCanvas);
        let snowflakeMaterial = new THREE.PointsMaterial({
            size: 1,
            map: snowflakeTexture,
            transparent: true,
            blending: THREE.AdditiveBlending,
            depthTest: false
        });

        // 创建雪花粒子系统
        let snowflakeGeometry = new THREE.BufferGeometry();
        let snowflakeCount = 1000;
        let snowflakePositions = [];
        for (let i = 0; i < snowflakeCount; i++) {
            let x = Math.random() * 100 - 50;
            let y = Math.random() * 100 - 50;
            let z = Math.random() * 100 - 50;
            snowflakePositions.push(x, y, z);
        }
        snowflakeGeometry.setAttribute('position', new THREE.Float32BufferAttribute(snowflakePositions, 3));
        let snowflakeSystem = new THREE.Points(snowflakeGeometry, snowflakeMaterial);
        scene.add(snowflakeSystem);

        snowflakes.push(snowflakeSystem);
    }

    function animate() {
        requestAnimationFrame(animate);

        // 雪花飘落效果
        snowflakes.forEach(flake => {
            let positions = flake.geometry.attributes.position.array;
            for (let i = 0; i < positions.length; i += 3) {
                positions[i + 1] -= Math.random() * 0.5;
                if (positions[i + 1] < -50) {
                    positions[i + 1] = 50;
                }
            }
            flake.geometry.attributes.position.needsUpdate = true;
        });

        renderer.render(scene, camera);
    }
</script>
</body>
</html>
